/*
 * PongAI.hpp
 *
 *  Created on: Jun 25, 2009
 *      Author: asantos
 */

#ifndef PONGAI_HPP_
#define PONGAI_HPP_

class PongAIController{
private:
	SignalBroker& signalbroker;
	boost::signals::connection getselectedscenegraphconnection;
	Signal<PongLogic::PlayerStartTurnHandler>& player1startturn;
	Signal<PongLogic::PlayerStartTurnHandler>& player2startturn;
	Signal<PongLogic::BallInPlayHandler>& ballinplay;
	Signal<ClockView::TickHandler>& clocktick;


	enum State{Player1StartTurn, Player2StartTurn, BallInPlay};
	State currentstate;


	int player1_score;
	int player2_score;

	bool initialized;
	const SceneNode* ballnode;
	const SceneNode* player1node;
	const SceneNode* player2node;
	const PositionProperty* ballposition;
	const PositionProperty* player1position;
	const PositionProperty* player2position;
public:
	PongAIController(SignalBroker& signalbroker):
		signalbroker(signalbroker),
		player1startturn(signalbroker.CreateOrGetExistingSignal<PongLogic::PlayerStartTurnHandler>("/logic/player1/startturn")),
		player2startturn(signalbroker.CreateOrGetExistingSignal<PongLogic::PlayerStartTurnHandler>("/logic/player2/startturn")),
		ballinplay(signalbroker.CreateOrGetExistingSignal<PongLogic::BallInPlayHandler>("/logic/ball/inplay")),
		clocktick(signalbroker.CreateOrGetExistingSignal<ClockView::TickHandler>("/clock/tick")),
		initialized(false)
{

		Signal<SceneGraphController::GetSelectedSceneGraphHandler>& getselectedscenegraph = signalbroker.CreateOrGetExistingSignal<SceneGraphController::GetSelectedSceneGraphHandler>("/scenegraphcontroller/getselectedscenegraph");
		getselectedscenegraphconnection = getselectedscenegraph.connect(boost::bind(&PongAIController::GetSelectedSceneGraph, this, _1));

		player1startturn.connect(boost::bind(&PongAIController::HandlePlayer1StartTurn, this));
		player2startturn.connect(boost::bind(&PongAIController::HandlePlayer2StartTurn, this));
		ballinplay.connect(boost::bind(&PongAIController::HandleBallInPlay, this));
		clocktick.connect(boost::bind(&PongAIController::AITick, this, _1, _2));

	}
	void GetSelectedSceneGraph(SceneGraph& scenegraph){
		try{
			ballnode = scenegraph.GetRoot().GetChildNodePtrByName("ball");
			player1node = scenegraph.GetRoot().GetChildNodePtrByName("paddle0");
			player2node = scenegraph.GetRoot().GetChildNodePtrByName("paddle1");


			ballposition = &ballnode->GetSceneNodeProperty<PositionProperty>("position");
			player1position = &player1node->GetSceneNodeProperty<PositionProperty>("position");
			player2position = &player2node->GetSceneNodeProperty<PositionProperty>("position");


			getselectedscenegraphconnection.disconnect();
			initialized = true;
		}catch(...){

		}
	}
	void HandlePlayer1StartTurn(){
		currentstate = Player1StartTurn;
	}
	void HandlePlayer2StartTurn(){
		currentstate = Player2StartTurn;
	}
	void HandleBallInPlay(){
		currentstate = BallInPlay;
	}
	void AITick(long t, long dt){
		if(initialized){
			float player1y = player1position->GetPosition()(1,3);
			float player2y = player2position->GetPosition()(1,3);
			float bally = ballposition->GetPosition()(1,3);

			switch(currentstate){
			case Player1StartTurn:
				//match player1's position
				if(player2y < player1y - 1){
					signalbroker.InvokeSignal<Simulation1InputView::PlayerMovementHandler>("/input/player2/movedown", t, dt);

				}else if(player2y > player1y + 1){
					signalbroker.InvokeSignal<Simulation1InputView::PlayerMovementHandler>("/input/player2/moveup", t, dt);
				}

				//signalbroker.InvokeSignal("/input/player2/select", ArgsList());
				break;
			case Player2StartTurn:
				//move away from player1's paddle
				signalbroker.InvokeSignal<Simulation1InputView::PlayerSelectHandler>("/input/player2/select", t, dt);
				break;

			case BallInPlay:
				//move toward ball-y
				if(player2y < bally - 1){
					signalbroker.InvokeSignal<Simulation1InputView::PlayerMovementHandler>("/input/player2/movedown", t, dt);

				}else if(player2y > bally + 1){
					signalbroker.InvokeSignal<Simulation1InputView::PlayerMovementHandler>("/input/player2/moveup", t, dt);
				}
				break;
			}
		}
	}
};


#endif /* PONGAI_HPP_ */
